
#ifndef __log4cplus_export__h__
#define __log4cplus_export__h__

#include <string>
#include <ostream>
#include <sstream>

#ifndef UNICODE
#	ifndef tstring
#		define tstring std::string
#	endif
#	ifndef tchar
#		define tchar char
#	endif
#else
#	ifndef tstring
#		define tstring std::wstring
#	endif
#	ifndef tchar
#		define tchar wchar_t
#	endif
#endif

#ifndef UNICODE
#	define LOG_TEXT(STRING) STRING
#else
#	define LOG_TEXT(STRING) L##STRING
#endif

#ifndef UNICODE 
	typedef std::stringstream  tstream;
	typedef std::ostringstream tostream;
#else
	typedef std::wstringstream  tstream;
	typedef std::wostringstream tostream;
#endif

typedef void (*LOG_FUNC) (const tchar* msg, const tchar* file, unsigned int line);

//tstream& operator<<(tstream& ss, const tchar* psz);

struct LOG_FUNCS
{
	LOG_FUNC log_trace;
	LOG_FUNC log_info;
	LOG_FUNC log_debug;
	LOG_FUNC log_warn;
	LOG_FUNC log_error;
	LOG_FUNC log_fatal;
};

extern LOG_FUNCS g_log_funcs;

void init_log4cplus   (const char* mod_name);
void config_log4cplus (const char* file);
void fini_log4cplus   ();

class TracingObject 
{
public:
	TracingObject (const tchar* msg, tchar* file, unsigned int line)
	{
		_msg  = msg;
		_file = file;
		_line = line;
		tstring tmp = LOG_TEXT ("Enter: ");
		tmp += _msg;
		if (g_log_funcs.log_trace)
			g_log_funcs.log_trace (tmp.c_str (), _file.c_str (), line);
	}

	~TracingObject ()
	{
		tstring tmp = LOG_TEXT ("Exit: ");
		tmp += _msg;
		if (g_log_funcs.log_trace)
			g_log_funcs.log_trace (tmp.c_str (), _file.c_str (), _line);
	}

protected:
	tstring _msg;
	tstring _file;
	unsigned int _line;
};


#define LOG_METHOD(logEvent) TracingObject __tracing_obj (logEvent, __FILE__, __LINE__);

#define LOG_TRACE(logEvent)  \
	do { \
		if (g_log_funcs.log_trace ) {\
			tstream ss; \
			ss << logEvent; \
			g_log_funcs.log_trace (ss.str ().c_str (), __FILE__, __LINE__); \
		} \
	} while (0)

#define LOG_INFO(logEvent)  \
	do { \
		if (g_log_funcs.log_trace ) {\
			tstream ss; \
			ss << logEvent; \
			g_log_funcs.log_info (ss.str ().c_str (), __FILE__, __LINE__); \
		} \
	} while (0)

#define LOG_DEBUG(logEvent)  \
	do { \
		if (g_log_funcs.log_trace ) {\
			tstream ss; \
			ss << logEvent; \
			g_log_funcs.log_debug (ss.str ().c_str (), __FILE__, __LINE__); \
		} \
	} while (0)

#define LOG_WARN(logEvent)  \
	do { \
		if (g_log_funcs.log_trace ) {\
			tstream ss; \
			ss << logEvent; \
			g_log_funcs.log_warn (ss.str ().c_str (), __FILE__, __LINE__); \
		} \
	} while (0)

#define LOG_ERROR(logEvent) \
	do { \
		if (g_log_funcs.log_trace ) {\
			tstream ss; \
			ss << logEvent; \
			g_log_funcs.log_error (ss.str ().c_str (), __FILE__, __LINE__); \
		} \
	} while (0)


#define LOG_FATAL(logEvent)  \
	do { \
		if (g_log_funcs.log_trace ) {\
			tstream ss; \
			ss << logEvent; \
			g_log_funcs.log_fatal (ss.str ().c_str (), __FILE__, __LINE__); \
		} \
	} while (0)

#define LOG_ERROR_RETURN(ret, logEvent) do{ \
	LOG_ERROR(logEvent); \
	return ret; \
} while (0)

#define LOG_FATAL_RETURN(ret, logEvent) do{ \
	LOG_FATAL(logEvnet); \
	return ret; \
} while (0)


#endif // __log4cplus_export__h__